/*
 * Vector3.cpp
 *
 *  Created on: 2011/06/22
 *      Author: naoki
 */

#include "NTEngine/NTEngine.h"
#include "NTEngine/Math/Function.h"
#include "NTEngine/Math/Vector3.h"

namespace NTEngine {
namespace Math {

const Vector3 ZERO_VECTOR3(0.0F, 0.0F, 0.0F);

Vector3::Vector3( float a )
: x( a ), y( a ), z( a ) {
}

Vector3::Vector3( float aX, float aY, float aZ )
: x( aX ), y( aY ), z( aZ ) {
}

Vector3::Vector3( const Vector3& a )
: x( a.x ), y( a.y ), z( a.z ) {
}

Vector3& Vector3::operator=( const Vector3& a ) {
	x = a.x;
	y = a.y;
	z = a.z;
	return *this;
}

Vector3 Vector3::operator-() const {
	return Vector3( -x, -y, -z );
}

void Vector3::operator+=( const Vector3& a ) {
	x += a.x;
	y += a.y;
	z += a.z;
}

void Vector3::operator-=( const Vector3& a ) {
	x += a.x;
	y += a.y;
	z += a.z;
}

void Vector3::operator*=( float a ) {
	x *= a;
	y *= a;
	z *= a;
}

void Vector3::operator/=( float a ) {
	float rcp_a = 1.0F / a;
	x *= rcp_a;
	y *= rcp_a;
	z *= rcp_a;
}

float Vector3::operator*( const Vector3& a ) const {
	return ( x * a.x ) + ( y * a.y ) + ( z * a.z );
}

float& Vector3::operator[]( int i ) {
	ASSERT( ( i >= 0 ) && ( i < 3 ) );
	return ( &x )[ i ];
}

float Vector3::operator[]( int i ) const {
	ASSERT( ( i >= 0 ) && ( i < 3 ) );
	return ( &x )[ i ];
}

bool Vector3::operator==( const Vector3& a ) const {
	return ( x == a.x ) && ( y == a.y ) && ( z == a.z );
}

bool Vector3::operator!=( const Vector3& a ) const {
	return ( x != a.x ) || ( y != a.y ) || ( z != a.z );
}

float operator*( const Vector3& a, const Vector3& b ) {
	return ( a.x * b.x ) + ( a.y * b.y ) + ( a.z * b.z );
}

void Vector3::zero() {
	x = y = z = 0;
}

void Vector3::normalize() {
	float t = ( x * x ) + ( y * y ) + ( z * z );
	ASSERT( t > 0 ); // ゼロベクタじゃないよね
	t = 1.F / sqrt( t );
	x *= t;
	y *= t;
	z *= t;
}

float Vector3::length() const {
	return sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
}

float Vector3::squareLength() const {
	return ( x * x ) + ( y * y ) + ( z * z );
}

void Vector3::set( float ax, float ay, float az ) {
	x = ax;
	y = ay;
	z = az;
}

void Vector3::setAdd( const Vector3& a, const Vector3& b ) {
	x = a.x + b.x;
	y = a.y + b.y;
	z = a.z + b.z;
}

void Vector3::setAdd( const Vector3& a, float t ) {
	x = a.x + t;
	y = a.y + t;
	z = a.z + t;
}

void Vector3::setSub( const Vector3& a, const Vector3& b ) {
	x = a.x - b.x;
	y = a.y - b.y;
	z = a.z - b.z;
}

void Vector3::setSub( const Vector3& a, float t ) {
	x = a.x - t;
	y = a.y - t;
	z = a.z - t;
}

void Vector3::setMul( const Vector3& a, float t ) {
	x = a.x * t;
	y = a.y * t;
	z = a.z * t;
}

void Vector3::setMul( const Vector3& a, const Vector3& b ) {
	x = a.x * b.x;
	y = a.y * b.y;
	z = a.z * b.z;
}

void Vector3::setCross( const Vector3& a, const Vector3& b ) {
	x = a.y * b.z - a.z * b.y;
	y = a.z * b.x - a.x * b.z;
	z = a.x * b.y - a.y * b.x;
}

void Vector3::madd( const Vector3& a, float b ){
	x += a.x * b;
	y += a.y * b;
	z += a.z * b;
}

void Vector3::madd( const float* a, float b ){
	x += a[ 0 ] * b;
	y += a[ 1 ] * b;
	z += a[ 2 ] * b;
}

void Vector3::msub( const Vector3& a, float b ){
	x -= a.x * b;
	y -= a.y * b;
	z -= a.z * b;
}

} // namespace Math
} // namespace NTEngine
